package com.carleasoft.mps.core.quartz;

import org.quartz.*;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * <p>Description: 企业级定时任务调度</p>
 * @since 2019-12-06
 * @author haoyi
 */
@Component
public class QuartzManager {

    private Logger log = LoggerFactory.getLogger(QuartzManager.class);

    /**
     * 任务调度
     */
    @Autowired
    private Scheduler scheduler;

    //默认Job组名
    public static String JOB_GROUP_NAME = "DEFAULT_JOB_GROUP_NAME";
    //默认触发器组名
    public static String TRIGGER_GROUP_NAME = "DEFAULT_TRIGGER_GROUP_NAME";

    /**
     * @Description: 添加一个定时任务（无JobDataMap）
     * @param jobName 任务名
     * @param jobGroupName  任务组名
     * @param triggerGroupName 触发器组名
     * @param jobClass  任务job
     * @param cron   时间设置，参考quartz说明文档
     */
    public void addJob(String jobName, String jobGroupName, String triggerGroupName,Class jobClass, String cron) {
        try {
            // 任务名，任务组，任务执行类
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
            //根据cron，构建一个CronTrigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, triggerGroupName).withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();
            //启动
            scheduler.scheduleJob(jobDetail, trigger);
            if (!scheduler.isShutdown()) {
                scheduler.start();
                log.info("任务名为："+jobName+"，的定时任务添加成功！");
            }
        } catch (Exception e) {
            log.error("添加定时任务失败！",e);
        }
    }

    /**
     * @Description: 添加一个定时任务（有JobDataMap）
     * @param jobName 任务名
     * @param jobGroupName  任务组名
     * @param triggerGroupName 触发器组名
     * @param jobClass  任务job
     * @param jobDataMap  job参数
     * @param cron   时间设置，参考quartz说明文档
     */
    public void addJob(String jobName, String jobGroupName,JobDataMap jobDataMap, String triggerGroupName,Class jobClass, String cron) {
        try {
            // 任务名，任务组，任务执行类
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).usingJobData(jobDataMap).build();
            //根据cron，构建一个CronTrigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, triggerGroupName).withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();
            //启动
            scheduler.scheduleJob(jobDetail, trigger);
            if (!scheduler.isShutdown()) {
                scheduler.start();
                log.info("任务名为："+jobName+"，的定时任务添加成功！");
            }
        } catch (Exception e) {
            log.error("添加定时任务失败！",e);
        }
    }

    /**
     * 修改任务时间
     *
     * @param jobName          任务名
     * @param time             crond格式时间
     * @param jobGroupName     任务组名
     * @param triggerGroupName 触发器组名
     * @param jobDataMap       附带参数，若为null则不需要添加参数
     */
    public void modifyJobTime(String jobName, String time, String jobGroupName,
                                        String triggerGroupName, JobDataMap jobDataMap) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, triggerGroupName);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if (trigger == null) {
                log.info("无"+jobName+"任务的触发器,请确认正确定时任务名称！");
                return;
            }
            String oldTime = trigger.getCronExpression();
            if (!oldTime.equalsIgnoreCase(time)) {
                JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
                JobDetail jobDetail = scheduler.getJobDetail(jobKey);
                Class<? extends Job> jobClass = jobDetail.getJobClass();
                removeJob(jobName,jobGroupName,triggerGroupName);
                if(jobDataMap != null){
                    this.addJob(jobName,jobGroupName,jobDataMap,triggerGroupName,jobClass,time);
                }else {
                    this.addJob(jobName,jobGroupName,triggerGroupName,jobClass,time);
                }
            }
            log.info("任务名为："+jobName+"，的定时任务修改成功！");
        } catch (Exception e) {
            log.error("修改定时任务失败！",e);
        }
    }

    /**
     * 删除一个定时任务
     * @param jobName                任务名称
     * @param jobGroupName          任务组名
     * @param triggerGroupName     触发器组名
     */
    public void removeJob(String jobName, String jobGroupName, String triggerGroupName) {
        try {
            TriggerKey triggerKey = new TriggerKey(jobName,triggerGroupName);
            // 停止触发器
            scheduler.pauseTrigger(triggerKey);
            //移除触发器
            scheduler.unscheduleJob(triggerKey);
            // 删除任务
            scheduler.deleteJob(new JobKey(jobName,jobGroupName));
            log.info("任务名为："+jobName+"，的定时任务删除成功！");
        } catch (Exception e) {
            log.error("删除定时任务失败！",e);
        }
    }

    /**
     * 判断是否存在该定时任务
     * @param jobName      任务名
     * @param jobGroupName 任务组名
     * @return boolean 是否存在JobKey
     */
    public boolean isJobKey(String jobName, String jobGroupName) {
        boolean bool = false;
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            JobDetail jobDetail = scheduler.getJobDetail(jobKey);
            if(jobDetail != null){
                bool = true;
            }
        } catch (Exception e) {
            log.error("判断是否存在该定时任务失败！",e);
        }
        return bool;
    }

    /**
     * 启动所有定时任务
     * @return boolean 是否启动成功
     */
    public boolean startJobs() {
        boolean bool = false ;
        try {
            scheduler.start();
            bool = true ;
        } catch (Exception e) {
            log.error("启动所有定时任务失败！",e);
        }
        return bool;
    }

    /**
     * 关闭所有定时任务
     * @return boolean 是否关闭成功
     */
    public boolean shutdownJobs() {
        boolean bool = false ;
        try {
            if (!scheduler.isShutdown()) {
                scheduler.shutdown();
            }
            bool = true;
        } catch (Exception e) {
            log.error("关闭所有定时任务失败！",e);
        }
        return bool;
    }
}
